package com.learning.platform.service;

import com.learning.platform.dto.NoteRequest;
import com.learning.platform.dto.NoteResponse;
import com.learning.platform.entity.Note;
import com.learning.platform.entity.Lesson;
import com.learning.platform.enums.ErrorCode;
import com.learning.platform.enums.NoteType;
import com.learning.platform.exception.BusinessException;
import com.learning.platform.repository.NoteRepository;
import com.learning.platform.repository.CourseRepository;
import com.learning.platform.repository.LessonRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 笔记服务类
 */
@Service
@Transactional
public class NoteService {
    
    private final NoteRepository noteRepository;
    private final CourseRepository courseRepository;
    private final LessonRepository lessonRepository;
    
    public NoteService(NoteRepository noteRepository, 
                      CourseRepository courseRepository,
                      LessonRepository lessonRepository) {
        this.noteRepository = noteRepository;
        this.courseRepository = courseRepository;
        this.lessonRepository = lessonRepository;
    }
    
    /**
     * 创建笔记
     */
    public NoteResponse createNote(Long userId, NoteRequest request) {
        // 验证课程是否存在（创建时courseId可选）
        if (request.getCourseId() != null) {
            courseRepository.findById(request.getCourseId())
                    .orElseThrow(() -> new BusinessException(ErrorCode.COURSE_NOT_FOUND));
            
            // 如果指定了章节，验证章节是否存在且属于该课程
            if (request.getLessonId() != null) {
                Lesson lesson = lessonRepository.findById(request.getLessonId())
                        .orElseThrow(() -> new BusinessException("章节不存在"));
                if (!lesson.getCourseId().equals(request.getCourseId())) {
                    throw new BusinessException("章节不属于指定课程");
                }
            }
        } else {
            // 课程ID为空时，章节ID也必须为空
            if (request.getLessonId() != null) {
                throw new BusinessException("未指定课程时，不能指定章节");
            }
        }
        
        // 创建笔记实体
        Note note = new Note();
        note.setUserId(userId);
        note.setCourseId(request.getCourseId());
        note.setLessonId(request.getLessonId());
        note.setVideoTimestamp(request.getVideoTimestamp());
        note.setTitle(request.getTitle());
        note.setContent(request.getContent());
        note.setTags(request.getTags());
        note.setNoteType(request.getNoteType());
        note.setIsPublic(request.getIsPublic());
        
        Note savedNote = noteRepository.save(note);
        
        return buildNoteResponse(savedNote);
    }
    
    /**
     * 更新笔记
     */
    public NoteResponse updateNote(Long userId, Long noteId, NoteRequest request) {
        Note note = noteRepository.findById(noteId)
                .orElseThrow(() -> new BusinessException("笔记不存在"));
        
        // 检查权限
        if (!note.getUserId().equals(userId)) {
            throw new BusinessException(ErrorCode.PERMISSION_DENIED);
        }
        
        // 验证课程是否存在（更新时courseId可以为null，表示取消关联）
        if (request.getCourseId() != null) {
            courseRepository.findById(request.getCourseId())
                    .orElseThrow(() -> new BusinessException(ErrorCode.COURSE_NOT_FOUND));
            
            // 如果指定了章节，验证章节是否存在且属于该课程
            if (request.getLessonId() != null) {
                Lesson lesson = lessonRepository.findById(request.getLessonId())
                        .orElseThrow(() -> new BusinessException("章节不存在"));
                if (!lesson.getCourseId().equals(request.getCourseId())) {
                    throw new BusinessException("章节不属于指定课程");
                }
            }
        } else {
            // 如果courseId为null，则lessonId也必须为null
            if (request.getLessonId() != null) {
                throw new BusinessException("取消课程关联时，章节关联也必须取消");
            }
        }
        
        // 更新笔记信息
        note.setCourseId(request.getCourseId());  // 添加课程ID更新（可以为null）
        note.setLessonId(request.getLessonId());  // 添加章节ID更新（可以为null）
        note.setTitle(request.getTitle());
        note.setContent(request.getContent());
        note.setTags(request.getTags());
        note.setNoteType(request.getNoteType());
        note.setIsPublic(request.getIsPublic());
        
        if (request.getVideoTimestamp() != null) {
            note.setVideoTimestamp(request.getVideoTimestamp());
        }
        
        Note updatedNote = noteRepository.save(note);
        return buildNoteResponse(updatedNote);
    }
    
    /**
     * 删除笔记
     */
    public void deleteNote(Long userId, Long noteId) {
        Note note = noteRepository.findById(noteId)
                .orElseThrow(() -> new BusinessException("笔记不存在"));
        
        // 检查权限
        if (!note.getUserId().equals(userId)) {
            throw new BusinessException(ErrorCode.PERMISSION_DENIED);
        }
        
        noteRepository.delete(note);
    }
    
    /**
     * 获取笔记详情
     */
    @Transactional(readOnly = true)
    public NoteResponse getNoteById(Long userId, Long noteId) {
        Note note = noteRepository.findById(noteId)
                .orElseThrow(() -> new BusinessException("笔记不存在"));
        
        // 检查权限（只能查看自己的笔记或公开笔记）
        if (!note.getUserId().equals(userId) && !note.getIsPublic()) {
            throw new BusinessException(ErrorCode.PERMISSION_DENIED);
        }
        
        return buildNoteResponse(note);
    }
    
    /**
     * 获取用户的所有笔记（分页）
     */
    @Transactional(readOnly = true)
    public Page<NoteResponse> getUserNotes(Long userId, int page, int size, String sortBy) {
        Sort sort = Sort.by(Sort.Direction.DESC, "createdAt");
        if ("title".equals(sortBy)) {
            sort = Sort.by(Sort.Direction.ASC, "title");
        } else if ("updated".equals(sortBy)) {
            sort = Sort.by(Sort.Direction.DESC, "updatedAt");
        }
        
        Pageable pageable = PageRequest.of(page, size, sort);
        Page<Note> notePage = noteRepository.findByUserIdOrderByCreatedAtDesc(userId, pageable);
        
        return notePage.map(this::buildNoteResponse);
    }
    
    /**
     * 获取课程笔记（分页）
     */
    @Transactional(readOnly = true)
    public Page<NoteResponse> getCourseNotes(Long userId, Long courseId, int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        Page<Note> notePage = noteRepository.findByUserIdAndCourseIdOrderByCreatedAtDesc(
                userId, courseId, pageable);
        
        return notePage.map(this::buildNoteResponse);
    }
    
    /**
     * 获取章节笔记
     */
    @Transactional(readOnly = true)
    public List<NoteResponse> getLessonNotes(Long userId, Long courseId, Long lessonId) {
        List<Note> notes = noteRepository.findByUserIdAndCourseIdAndLessonIdOrderByCreatedAtDesc(
                userId, courseId, lessonId);
        
        return notes.stream()
                .map(this::buildNoteResponse)
                .collect(Collectors.toList());
    }
    
    /**
     * 获取视频时间点笔记
     */
    @Transactional(readOnly = true)
    public List<NoteResponse> getVideoTimestampNotes(Long userId, Long lessonId) {
        List<Note> notes = noteRepository.findByUserIdAndLessonIdAndNoteTypeOrderByVideoTimestampAsc(
                userId, lessonId, NoteType.VIDEO_TIMESTAMP);
        
        return notes.stream()
                .map(this::buildNoteResponse)
                .collect(Collectors.toList());
    }
    
    /**
     * 搜索笔记
     */
    @Transactional(readOnly = true)
    public Page<NoteResponse> searchNotes(Long userId, String keyword, int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        Page<Note> notePage = noteRepository.searchByKeyword(userId, keyword, pageable);
        
        return notePage.map(this::buildNoteResponse);
    }
    
    /**
     * 根据标签获取笔记
     */
    @Transactional(readOnly = true)
    public List<NoteResponse> getNotesByTag(Long userId, String tag) {
        List<Note> notes = noteRepository.findByUserIdAndTag(userId, tag);
        
        return notes.stream()
                .map(this::buildNoteResponse)
                .collect(Collectors.toList());
    }
    
    /**
     * 根据标签搜索笔记
     */
    @Transactional(readOnly = true)
    public List<NoteResponse> searchNotesByTag(Long userId, String tag) {
        return getNotesByTag(userId, tag);
    }
    
    /**
     * 获取用户最常用的标签
     */
    @Transactional(readOnly = true)
    public List<String> getTopTags(Long userId, int limit) {
        List<Object[]> results = noteRepository.getTopTagsByUserId(userId, limit);
        
        return results.stream()
                .map(row -> (String) row[0])
                .collect(Collectors.toList());
    }
    
    /**
     * 统计用户笔记数量（指定时间范围）
     */
    @Transactional(readOnly = true)
    public long countNotesInTimeRange(Long userId, LocalDateTime startTime, LocalDateTime endTime) {
        return noteRepository.countByUserIdAndCreatedAtBetween(userId, startTime, endTime);
    }
    
    /**
     * 获取课程笔记统计
     */
    @Transactional(readOnly = true)
    public List<Object[]> getCourseNoteStats(Long userId, Long courseId) {
        return noteRepository.getNoteStatsByCourse(userId, courseId);
    }
    
    /**
     * 构建笔记响应对象
     */
    private NoteResponse buildNoteResponse(Note note) {
        NoteResponse response = new NoteResponse(note);
        
        // 设置课程标题（如果有课程ID）
        if (note.getCourseId() != null) {
            courseRepository.findById(note.getCourseId())
                    .ifPresent(course -> response.setCourseTitle(course.getTitle()));
        }
        
        // 设置章节标题
        if (note.getLessonId() != null) {
            lessonRepository.findById(note.getLessonId())
                    .ifPresent(lesson -> response.setLessonTitle(lesson.getTitle()));
        }
        
        return response;
    }
}
